package com.tarena.luban.test.repository.impl;

import com.tarena.luban.test.repository.cache.CacheEntry;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.util.List;
import java.util.concurrent.TimeUnit;

public class RedisCacheEntry<T> implements CacheEntry<T>, InitializingBean {
    @Autowired
    private RedisTemplate redisTemplate;
    private ValueOperations opsForValue;
    private ListOperations opsForList;
    @Override
    public Boolean exists(String key) {
        return redisTemplate.hasKey(key);
    }

    @Override
    public T getCache(String key) {
        return (T) opsForValue.get(key);
    }

    @Override
    public void saveCache(String key, T value) {
        //存储永久数据
        this.saveCache(key,value,null,null);
    }

    @Override
    public void saveCaches(String key,List<T> values) {
        this.saveCaches(key,values,null,null);
    }
    public void saveCaches(String key,List<T> values, Long time,TimeUnit timeUnit){
        if (time==null||timeUnit==null){
            //lpush key value1 value2 value3
            opsForList.leftPushAll(key,values);
        }else{
            opsForList.leftPushAll(key,values);
            //expire key time计算的秒数
            redisTemplate.expire(key,time,timeUnit);
        }
    }

    @Override
    public List<T> getCaches(String key) {
        return opsForList.range(key,0,-1);
    }

    @Override
    public void delete(String key) {
        redisTemplate.delete(key);
    }

    public void saveCache(String key, T value, Long time, TimeUnit timeUnit){
        if (time==null || timeUnit==null){
            //永久数据 time=null timeUnit=null
            opsForValue.set(key,value);
        }else {
            opsForValue.set(key,value,time,timeUnit);
        }
    }

    /**
     * 当前类的bean对象 在创建之后,进行afterPropertiesSet调用
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        this.opsForList=redisTemplate.opsForList();
        this.opsForValue=redisTemplate.opsForValue();
    }

    /**
     * @param key 和业务结合的锁的key值
     * @param value 空字符串,视情况而定.worker查询中,由于抢到锁的执行查询数据库
     *              没抢到的不会重抢,涉及不到释放锁释放错误的问题
     * @return
     */
    public Boolean tryLock(String key,String value){
        return opsForValue.setIfAbsent(key,value,10,TimeUnit.SECONDS);
    }
}
